﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class BlueprintBuilder {

    private const int ITERATIONS = 4;
    private const int MAXITERATIONSPERSPLIT = 20;

    private int minRoomSize = DataStorage.Instance.GetMinRoomSize();
    private int maxRoomSize = DataStorage.Instance.GetMaxRoomSize();

    private List<Room> rooms = new List<Room>();

    private bool intersected = false;
    private bool upperLineFinished = false;
    private bool mainRoomSplit = true;

    private string[,] tiles = null;

    private int roomWidthOffset = 2;
    private int randomRoomNumber = Random.Range(DataStorage.Instance.GetMinRooms(), DataStorage.Instance.GetMaxRooms());
    private int firstUnused = -1; //TODO: stupid value
    private int lastUnused = -1;

    private int roomsTemp = 4;

    private int yTemp = 0;

    private Room firstRoom = null;

    public void CreateRooms2()
    {
        tiles = MapOverview.Instance.GetTileMap();

        Room mainRoom = new Room(new Point(0, DataStorage.Instance.GetMapHeight()-1), DataStorage.Instance.GetMapWidth(), DataStorage.Instance.GetMapHeight());
        Tree tree = SplitRoom(mainRoom, ITERATIONS); //TODO:
        int a = 0;
        List<Room> hallo = tree.GetLeaves();

        foreach (Room b in hallo)
            b.MarkRoomInMap();

        DataStorage.Instance.SetRoomList(tree.GetLeaves());
        MapOverview.Instance.DeleteUnnecessary();
        MapOverview.Instance.SetCenterPoints();
        MapOverview.Instance.PrintMap();

        GraphBuilder graphBuilder = new GraphBuilder();
        graphBuilder.CreateGraph();
        graphBuilder.SelectEdges();

        MapOverview.Instance.InsertDoors();
        //MapOverview.Instance.PrintMap();

        SceneBuilder.Instance.BuildScene();

        InteriorDesigner interiorDesigner = new InteriorDesigner();
        interiorDesigner.FurnishRooms();
    }

    private Tree SplitRoom(Room room, int i)
    {
        Tree root = new Tree(room);
        if (i != 0 && (room.GetWidth() / 2 >= minRoomSize || room.GetHeight() / 2 >= minRoomSize))
        {
            List<Room> sr = RandomSplit(room, MAXITERATIONSPERSPLIT);
            if (sr != null)
            {
                root.leftChild = SplitRoom(sr[0], i - 1);
                root.rightChild = SplitRoom(sr[1], i - 1);
            }
        }
        return root;
}

    private List<Room> RandomSplit(Room room, int maxIterationsPerSplit)
    {
        maxIterationsPerSplit--;
        int randomNo;
        if (room.GetWidth() / 2 >= minRoomSize && room.GetHeight() / 2 < minRoomSize)
            randomNo = 0;
        if (room.GetHeight() / 2 >= minRoomSize && room.GetWidth() / 2 < minRoomSize)
            randomNo = 1;
        else
            randomNo = Random.Range(0, 2);

        Room r1, r2 = null;
        if (maxIterationsPerSplit == 0)
            return null;
        if (randomNo == 0)
        {
            // Vertical
            //if (mainRoomSplit)
            //{
            //    r1 = new Room(new Point(room.GetXLeft(), room.GetYTop()),             // r1.x, r1.y
            //            Random.Range(room.GetWidth() - 2, room.GetWidth() + 3), room.GetHeight());   // r1.w, r1.h
            //    r2 = new Room(new Point(room.GetXLeft() + r1.GetWidth() - 1, room.GetYTop()),      // r2.x, r2.y
            //            room.GetWidth() - r1.GetWidth() + 1, room.GetHeight());       // r2.w, r2.h
            //    mainRoomSplit = false;
            //}
            //else
            {
                r1 = new Room(
                    new Point(room.GetXLeft(), room.GetYTop()),             // r1.x, r1.y
                    Random.Range(0, room.GetWidth()), room.GetHeight());   // r1.w, r1.h
                r2 = new Room(
                    new Point(room.GetXLeft() + r1.GetWidth() - 1, room.GetYTop()),      // r2.x, r2.y
                    room.GetWidth() - r1.GetWidth() + 1, room.GetHeight());       // r2.w, r2.h
            }
            float r1Ratio = (float)r1.GetWidth() / r1.GetHeight();
            float r2Ratio = (float)r2.GetWidth() / r2.GetHeight();

            if (r1Ratio < 0.45 || r2Ratio < 0.45 || r1.GetWidth() < minRoomSize || r1.GetHeight() < minRoomSize || r2.GetWidth() < minRoomSize || r2.GetHeight() < minRoomSize)
                return RandomSplit(room, maxIterationsPerSplit);
        }
        else
        {
            // Horizontal
            //if (mainRoomSplit)
            //{
            //    r1 = new Room(new Point(room.GetXLeft(), room.GetYTop()),             // r1.x, r1.y
            //            room.GetWidth(), Random.Range(room.GetHeight() - 2, room.GetHeight() + 3));   // r1.w, r1.h
            //    r2 = new Room(new Point(room.GetXLeft(), room.GetYTop() - r1.GetHeight() + 1),      // r2.x, r2.y
            //            room.GetWidth(), room.GetHeight() - r1.GetHeight() + 1);       // r2.w, r2.h
            //    mainRoomSplit = false;
            //}
            //else
            {
                r1 = new Room(
                    new Point(room.GetXLeft(), room.GetYTop()),             // r1.x, r1.y
                    room.GetWidth(), Random.Range(0, room.GetHeight()));   // r1.w, r1.h
                r2 = new Room(
                    new Point(room.GetXLeft(), room.GetYTop() - r1.GetHeight() + 1),      // r2.x, r2.y
                    room.GetWidth(), room.GetHeight() - r1.GetHeight() + 1);       // r2.w, r2.h
            }

            float r1Ratio = (float)r1.GetHeight() / r1.GetWidth();
            float r2Ratio = (float)r2.GetHeight() / r2.GetWidth();
            if (r1Ratio < 0.45 || r2Ratio < 0.45 || r1.GetWidth() < minRoomSize || r1.GetHeight() < minRoomSize || r2.GetWidth() < minRoomSize || r2.GetHeight() < minRoomSize)
                return RandomSplit(room, maxIterationsPerSplit);
        }
        //if (randomNo == 0)
        //{
        //    // Vertical
        //    r1 = new Room(
        //        new Point(room.GetXLeft(), room.GetYTop()),             // r1.x, r1.y
        //        Random.Range(1, room.GetWidth()), room.GetHeight());   // r1.w, r1.h
        //    r2 = new Room(
        //        new Point(room.GetXLeft() + r1.GetWidth(), room.GetYTop()),      // r2.x, r2.y
        //        room.GetWidth() - r1.GetWidth(), room.GetHeight());       // r2.w, r2.h

        //}
        //else
        //{
        //    // Horizontal
        //    r1 = new Room(
        //        new Point(room.GetXLeft(), room.GetYTop()),             // r1.x, r1.y
        //        room.GetWidth(), Random.Range(1, room.GetHeight()));   // r1.w, r1.h
        //    r2 = new Room(
        //        new Point(room.GetXLeft(), room.GetYTop() - r1.GetHeight()),      // r2.x, r2.y
        //        room.GetWidth(), room.GetHeight() - r1.GetHeight());       // r2.w, r2.h
        //}
        List<Room> roomArray = new List<Room>();
        roomArray.Add(r1);
        roomArray.Add(r2);
        return roomArray;
    }




    public void CreateRooms()
    {
//        roomsTemp = rooms.Count + 20;

        tiles = MapOverview.Instance.GetTileMap();
        firstUnused = -1; //just some value, that can't be reached normally
        lastUnused = -1;
        for (int y = tiles.GetLength(1) - 1; y >= 0; y--)

        firstRoom = new Room(new Point(0, 29), 6, 6); //first
        rooms.Add(firstRoom);
        firstRoom.MarkRoomInMap();

        firstRoom = new Room(new Point(5, 29), 6, 7); //first
        rooms.Add(firstRoom);
        firstRoom.MarkRoomInMap();

        firstRoom = new Room(new Point(10, 29), 10, 9); //second
        rooms.Add(firstRoom);
        firstRoom.MarkRoomInMap();

        firstRoom = new Room(new Point(19, 29), 8, 10); //second
        rooms.Add(firstRoom);
        firstRoom.MarkRoomInMap();

        //firstRoom = new Room(21, 29, 29, 10);
        //rooms.Add(firstRoom);
        //firstRoom.MarkRoomInMap();

        //firstRoom = new Room(0, 23, 4, 10);
        //rooms.Add(firstRoom);
        //firstRoom.MarkRoomInMap();


        DataStorage.Instance.SetRoomList(rooms);


        for (int y = tiles.GetLength(1)-1; y >= 0; y--) // tiles.GetLength(1)
        {
            for (int x = 0; x < tiles.GetLength(0); x++)
            {
                //if (rooms.Count <= roomsTemp)
                //{
                    if (tiles[x, y] == "0" && firstUnused == -1) //if a tile is not  marked/used yet
                        firstUnused = x;
                    else if (firstUnused != -1 && tiles[x, y] == "w" && lastUnused == -1) //1. Case: if there's a gap between two rooms ...####*********#####|
                        lastUnused = x-1;
                    else if (firstUnused != -1 && x == tiles.GetLength(0) - 1 && lastUnused == -1) //2. Case: if a gap is at the end of a line ....######********|
                        lastUnused = x;
                    if (lastUnused != -1)
                    {
                        int randomWidth = 0;
                        int randomHeight = 0;
                        randomHeight = Random.Range(DataStorage.Instance.GetMinRoomSize(), DataStorage.Instance.GetMaxRoomSize());
                        randomWidth = Random.Range(DataStorage.Instance.GetMinRoomSize(), DataStorage.Instance.GetMaxRoomSize());

                        if (lastUnused + 1 - (firstUnused + randomWidth) < DataStorage.Instance.GetMinRoomSize() || firstUnused + randomWidth - 1 > DataStorage.Instance.GetMapWidth() - 1)//if there would not be enough room for another room, stretch this one out
                        {
                            if (lastUnused == DataStorage.Instance.GetMapWidth() - 1)
                                randomWidth = lastUnused - firstUnused + roomWidthOffset;
                            else if (firstUnused == 0)
                                randomWidth = lastUnused - firstUnused + roomWidthOffset;
                            else
                                randomWidth = lastUnused - firstUnused + roomWidthOffset + 1;
                        }
                            

                        if (y - randomHeight + 1 < 0) //if the randomHeight is too big to fit in
                            randomHeight = y + roomWidthOffset; //entspricht dem rest, der noch übrig ist
                        Room room;

                        //Checks, so that x and y isn't smaller than 0
                        if (firstUnused != 0 && y != DataStorage.Instance.GetMapHeight() - 1) //if unused doesn't intersect with any of the sides
                            room = new Room(new Point(firstUnused - 1, y + 1), randomWidth, randomHeight);
                        else if (firstUnused == 0 && y != DataStorage.Instance.GetMapHeight() - 1) //if unused is on left of map, but y-wise in the middle
                            room = new Room(new Point(firstUnused, y + 1), randomWidth, randomHeight);
                        else if (firstUnused != 0 && y == DataStorage.Instance.GetMapHeight() - 1) //if unused x-wise in the middle, but on the top
                            room = new Room(new Point(firstUnused - 1, y), randomWidth, randomHeight);
                        else /*if(firstUnused == 0 && y == DataStorage.Instance.GetMapHeight()-1)*/ //if unused is on left of map and on top (-> top-left corner)
                            room = new Room(new Point(firstUnused, y), randomWidth, randomHeight);

                        rooms.Add(room);
                        DataStorage.Instance.SetRoomList(rooms);
                        room.MarkRoomInMap();
                        tiles = MapOverview.Instance.GetTileMap();
                        if (firstUnused + randomWidth < 50 && tiles[firstUnused + randomWidth, y] == "0")
                            Debug.Log("ASDF");

                        firstUnused = -1;
                        lastUnused = -1;
                        x = -1; //so the loop goes another round for the same line
                    }
                //}

            }
        }

        DataStorage.Instance.SetRoomList(rooms);
        MapOverview.Instance.DeleteUnnecessary();
        MapOverview.Instance.SetCenterPoints();
        MapOverview.Instance.PrintMap();
        //foreach(Room roomElement in rooms)
        //{
        //    foreach (Room roomThin in rooms)
        //    {
        //        if (!roomElement.Equals(roomThin))
        //        {
        //            if (roomElement.IsNeighbour(roomThin))
        //                Debug.Log(roomThin.GetCenter().x + " " + roomThin.GetCenter().y);
        //        }
        //    }
        //}
        //SceneBuilder.Instance.BuildScene();

        GraphBuilder graphBuilder = new GraphBuilder();
        graphBuilder.CreateGraph();
        graphBuilder.SelectEdges();

        MapOverview.Instance.InsertDoors();
        //MapOverview.Instance.PrintMap();

        SceneBuilder.Instance.BuildScene();

        InteriorDesigner interiorDesigner = new InteriorDesigner();
        interiorDesigner.FurnishRooms();

    }

    private void CreateRandomRoom()
    {

    }
}
